package org.common.utils.handler;
import cn.hutool.core.util.ClassUtil;
import org.common.utils.function.BiConsumerThrows;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 初始化处理实现类工具
 */
public class HandlerTool {

    public static <T> Map<Class<?> , T> initChildHandler(String packageString , Class<T> fatherClass) {
        Set<Class<?>> classSet = ClassUtil.scanPackage(packageString);
        return initChildHandler(classSet , packageString, fatherClass , (map , clzss) -> {
            T value = (T)clzss.getConstructor().newInstance();
            map.put(clzss , value);
        });
    }

    public static <R , T> Map<R , T> initChildHandler(String packageString , Class<T> fatherClass ,  HandlerKey<R, T> handlerKey) {
        Set<Class<?>> classSet = ClassUtil.scanPackage(packageString);
        return initChildHandler(classSet , packageString , fatherClass , (map , clzss) -> {
            T value = (T)clzss.getConstructor().newInstance();
            R key = handlerKey.getKey(value);
            map.put(key , value);
        });
    }

    /**
     * 加载并初始化子类处理器
     * @param packageString 包路径
     * @param fatherClass 父类
     * @param consumer 处理
     * @return 返回以指定key的子类处理器列表
     * @param <T> 泛型
     */
    private static  <T , K , V> Map<K , V> initChildHandler(Set<Class<?>> classSet , String packageString , Class<T> fatherClass , BiConsumerThrows<Map<K , V> , Class<?>> consumer) {
        ConcurrentHashMap<K , V> map = new ConcurrentHashMap<>();
        Class<?> currentClzss = null;
        try {
            for (Class<?> clzss : classSet) {
                int modifiers = clzss.getModifiers();
                //是抽象类、接口
                if(Modifier.isAbstract(modifiers) || Modifier.isInterface(modifiers))
                    continue;
                //不是fatherClass类的子类
                if(!fatherClass.isAssignableFrom(clzss))
                    continue;

                currentClzss = clzss;
                consumer.accept(map , currentClzss);
            }
        } catch (Exception e) {
            throw new RuntimeException("HandlerTool.initChildHandler currentClass = " + currentClzss.getName() + " , fatherClass " + fatherClass + " , packageString " + packageString, e);
        }

        if(map.isEmpty()) {
            throw new RuntimeException("HandlerTool.initChildHandler map empty, " + (currentClzss == null ? null : currentClzss.getName()) + " , fatherClass " + fatherClass + " , packageString " + packageString);
        }
        return map;
    }

    /**
     * 处理器获取key接口
     * <R T> R返回值泛型 , T当前对象泛型。
     */
    public interface HandlerKey<R, T> {
        R getKey(T t);
    }
}
